﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Threading;
using System.Net.Sockets;
using System.Net;
using System.IO;
using System.Diagnostics;

namespace AbyssCombatLogger
{
    class Client
    {
        Queue<ParsedLogEvent> TargetDamagesToUpload = new Queue<ParsedLogEvent>();
        Queue<ParsedLogEvent> targetHealsToUpload = new Queue<ParsedLogEvent>();

        public struct ClientMessage
        {
            public string Client;
            public Hashtable Message;
        }

        private Queue<ClientMessage> qClientMessages = new Queue<ClientMessage>();

        string PlayerName = null;

        private Hashtable htDamageDealers = new Hashtable();
        private Hashtable htClientPlayers = new Hashtable(); 

        Thread clientThread = null;

        TcpClient client = null;
        IPEndPoint serverEndPoint = null;
        NetworkStream clientStream = null;

        Hashtable newGroupData = null;

        int clientWait = 100; //ms

        public void CloseEverything()
        {
            if (clientStream != null)
                clientStream.Close();
            if (clientThread != null)
                this.clientThread.Abort();

            if (clientThread != null)
                clientThread.Abort();
            if (client != null)
                client.Close();
        }
  

         ////
        ////Begin Client code       
        private void ClientCommunication()
        {  
            //first message and duty upon connection is sending the player name
            if (client.Connected == false)
                clientStream = null;
            else if (clientStream == null)
                clientStream = client.GetStream();
            if (clientStream == null)
                return;

            try
            {
                StreamWriter sw = new StreamWriter(clientStream);
                sw.WriteLine(PlayerName);
                sw.Flush();
                //break;
            }
            catch (Exception commError)
            {
                Debug.WriteLine(commError.Message + "\n"+commError.ToString());
                return;
            }

            while (true) //client != null && client.Connected)
            {
                try
                {


                    // do inverse of 
                    //WriteTo(clientStream, serverDamageForAllUsers);
                    //newDamagesFromClient = (Queue<StringNumber<int>>)ReadFrom(clientStream);
                    //newHealsFromClient = (Queue<StringNumber<int>>)ReadFrom(clientStream);
                    //


                    newGroupData = (Hashtable)Server.ReadFrom(clientStream, "Client");
                    //for debugging purposes only
                    //if (newGroupData != null && newGroupData.Count > 0)
                    //    Debug.Assert(false);
                    //if (SNPair<long>sToUpload != null && SNPair<long>sToUpload.Count > 0)
                    //    Debug.Assert(false);
                    //if (targetHealsToUpload != null && targetHealsToUpload.Count > 0)
                    //    Debug.Assert(false);

                    Server.WriteTo(clientStream, TargetDamagesToUpload, "Client");
                    Server.WriteTo(clientStream, targetHealsToUpload, "Client");

                    //dont need hostile targets on server side any more, but need to make code so dont have to send.
                    //for now leave in because it has purpose but remove for bandwidth and do accounting on server for bandwidth saving

                    // add this field to your class

                    //                    int readCount = 0;

                    //                   if(bytesRead > 0)
                    //                  {
                    // comment this out for now...
                    // BinaryFormatter binaryFormatter = new BinaryFormatter();

                    // buffer is whatever class field you passed into the
                    //clientStream.BeginRead();
                    //MessageBox.Show(String.Format("Read #{0} = {1}" ++readCount,
                    // Encoding.ASCII.GetString(buffer, 0, bytesRead));
                    //                    }
                    //clientStream.BeginRead(        

                    //now clear the queues (not the hashtables) for adding more data 
                    TargetDamagesToUpload.Clear();
                    targetHealsToUpload.Clear();

                    //if (cbServerRunning.Checked)
                    //{
                    //    //dont mix the servers info with what the clients will get and will be mostly the same if not identical for now.
                    //}
                    //else
                    //{
                    
                    htDamageDealers = newGroupData;

                    //clientStream.Close();
                }
                catch (Exception transferError)
                {
                    InfoLogIt("There was a transfer error from your client to the server.. ", transferError, "Communication error: Cannot transfer data.");
                    break;
                }

                //tmrClientSend.Enabled = true;
                clientThread.Join(clientWait);
            }
        }

        private void InfoLogIt(string p, Exception transferError, string speakText)
        {
            throw new NotImplementedException();
        }

    }
}
